/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       random_town.cpp

	$Header: /game/random_town.cpp $

	$NoKeywords: $

 ************************************************************************/

// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "random_town.h"

#include "adv_object_type.h"
#include "adventure_map.h"
#include "building_traits.h"
#include "object_registration.h"
#include "player.h"
#include "player_color.h"
#include "random.h"
#include "town.h"
#include "town_school_skills.h"

namespace
{
	int const k_current_map_format_version = 7;

	t_object_registration<t_random_town> k_registration( k_adv_object_random_town );
}


// ---------------------------------------------------------------
// random town object
// ---------------------------------------------------------------
t_random_town::t_random_town( std::string const& source )
             : t_abstract_town( source ),
			   m_linkage_info( false )
{
}

// ---------------------------------------------------------------
// random town object
// ---------------------------------------------------------------
bool t_random_town::read_from_map( std::streambuf& stream, t_progress_handler* handler )
{

	int version = get< t_uint16 >( stream );
	if ( version < 0 || version > k_current_map_format_version )
		return false;

	if ( version >= 7 )
	{
		if (	!m_linkage_info.read_from_map( stream )
			||	!t_abstract_town::read_map_data(
					stream,
					handler,
					m_custom_garrison,
					m_custom_buildings,
					m_customize_school_skills,
					m_available_school_skills,
					m_required_school_skills ) )
			return false;
	}
	else
	{
		m_linkage_info.reset();

		if (	!t_abstract_town::read_map_data(
					stream,
					handler,
					m_custom_garrison, 
					m_custom_buildings,
					m_customize_school_skills,
					m_available_school_skills,
					m_required_school_skills,
					version ) )
			return false;
	}

	return true;
}

// ---------------------------------------------------------------
// random town object
// ---------------------------------------------------------------
bool t_random_town::preplacement( t_adventure_map& map, int pass )
{
	if ( pass == 0 )
	{
		t_linkage_data::t_link_alignment link_alignment = m_linkage_info.get_link_alignment( map, pass );

		assert( link_alignment != t_linkage_data::k_link_alignment_wait );

		if (   link_alignment == t_linkage_data::k_link_alignment_any 
			|| link_alignment == t_linkage_data::k_link_alignment_wait )
		{
			// Use player alignment if belong to player, otherwise random
			if ( get_player_color() == k_player_gray )
			{
				m_type = random( k_town_type_count );
			}
			else
			{
				int owner = map.get_player_number( get_player_color() );
				m_type = map.get_player( owner ).get_alignment();
			}
		}
		else
		{
			m_type = t_linkage_data::link_alignment_to_town_type( link_alignment );
		}

		t_town_image_level	image_level = get_castle_level();
		t_two_way_facing	facing = t_two_way_facing( get_major_subtype() );
		char const*			new_name;
		
		new_name = get_town_model_name( m_type, image_level, facing );
		set_model( new_name );

		m_town = new t_town( this );
		m_town->create_spells( k_town_default_required_spells, k_town_default_potential_spells,
							   map );
		if (!m_custom_buildings)
			m_town->set_start_buildings();
		if (!m_custom_garrison)
			m_town->set_start_creatures();
		m_town->set_start_population();

		if ( !m_customize_school_skills )
		{
			m_available_school_skills.set();
			m_required_school_skills.reset();
		}

		m_town->setup_school_skills( m_available_school_skills, m_required_school_skills, map.get_allowed_skills() );
	}

	return m_town->preplacement( map, pass );
}

// ---------------------------------------------------------------
// random town object
// ---------------------------------------------------------------
void t_random_town::place( t_adventure_map& map, t_adv_map_point const& point )
{
	if ( m_town )
		m_town->place( map, point );
}
